#pragma once

#include<iostream>
#include<sys/ipc.h>
#include<sys/shm.h>

const int msize = 128;

#define PATHNAME "/tmp"
#define PROJ 0x66

class Shm
{
public:

    Shm(int size=msize)
    :_shmid(-1)
    ,_size(size)
    ,_start_addr(nullptr)
    {}

    void Attach()
    {
        _start_addr=shmat(_shmid,nullptr,0);
        if ((long long int)_start_addr==-1)
        {
            perror("Attach");
            exit(2);
        }
        
    }

    void Detach()
    {
        int n=shmdt(_start_addr);
        if(n==-1)
        {
            perror("Detach");
            exit(2);
        }
    }

    int Creat()
    {
        return getHelper(IPC_CREAT|IPC_EXCL|0666);
    }

    int Get()
    {
        return getHelper(IPC_CREAT);
    }

    void Delete()
    {
        int n=shmctl(_shmid,IPC_RMID,nullptr);
        if(n==-1)
        {
            perror("Delete");
            exit(3);
        }
    }

    int GetSize()
    {
        return _size;
    }

    void* GetStartAddr()
    {
        return _start_addr;
    }

    ~Shm(){}

private:

    key_t getKey()
    {
        return ftok(PATHNAME,PROJ);
    }

    int getHelper(int flg)
    {
        key_t key=getKey();
        if(key<0)
        {
            perror("getKey");
            return -1;
        }
        _shmid=shmget(key,_size,flg);
        if(_shmid==-1)
        {
            perror("getHelper");
            return -1;
        }
        return 0;
    }

private:
    int _shmid;
    int _size;
    void* _start_addr;
};